﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;

using Bling.Core;
using Bling.WPF;
using Bling.WPF.Util;
using Bling.Slides;
using Bling.Util;
using Bling.Shaders;
using Bling.Graphics;
namespace Bling.Tutorial {
  using Bling.Matrices;
  using Bling.WPF3D;
  using Bling.Shaders.DX;

  public class D3DTest : Canvas, ICanStart {
    private ICanStart Host;
    public void Start() { Host.Start(); }
    public void Stop() { Host.Stop(); }

    public D3DTest() {
      var AutumnUri = "Resources/dock1.jpg".MakePackUri(typeof(D3DTest));
      var NormalUri = "Resources/890-normal.jpg".MakePackUri(typeof(D3DTest));

      var Device = new RenderDevice();
      var sliderX = new LabelSliderBl(this) {
        LabelName = "X",
        ZIndex = 100,
      };
      var sliderY = new LabelSliderBl(this) {
        LabelName = "Y",
        ZIndex = 100,
        LeftTop = sliderX.LeftBottom,
      };
      var sliderZ = new LabelSliderBl(this) {
        LabelName = "Z",
        ZIndex = 100,
        LeftTop = sliderY.LeftBottom,
      };
      var world = sliderX.Value.PI2().RotateAround(new Point3DBl(1d, 1d, sliderZ));
      world = world * sliderY.Value.PI2().RotateAround(new Point3DBl(sliderZ, 1d, 1d));

      var eye = new Point3DBl(0f, -2d, -4d);
      var at = new Point3DBl(0f, 0f, 0f);
      var up = new Point3DBl(0f, 1f, 0f);
      var view = eye.LookAtLH(at, up);
      var project = (.25.PI()).PerspectiveFovLh(500d / 500d, .1, 100d);
      var ambLight = new AmbientLightBl() { Color = Colors.White.Bl() };
      var dirLight = new DirectionalLightBl() {
        Direction = new Point3DBl(1, 0, 0).Normalize,
        Color = Colors.White.Bl(),      };           
      var spotLight = new SpotLightBl() {
        Direction = new Point3DBl(1, -1, 1).Normalize,
        Color = Colors.Red.Bl(),
        Position = new Point3DBl(-2, 2, -2),
        InnerConeAngle = 50.ToDegrees(),
        OuterConeAngle = 180.ToDegrees(),
      };

      var Surface = Geometries.Sphere;//.Displace((Geometries.EggCrate.Frequency(30d).Magnitude(.05d)));
      var SurfaceKeys = new ParametricKeys(100, 100);

      // easier...
      var Autumn = Device.TextureFromUri(AutumnUri);
      var Normal0 = Device.TextureFromUri(NormalUri);

      Device.Render(SurfaceKeys, (n, uv, vertex) => {

        //var k = (n / 10) + (n % 10);
        var clr = Autumn[uv + 0.5];
         //clr = new ColorBl(clr.Z, clr.Y, clr.X, clr.W);
        vertex.Position = (Surface * (world * view * project))[uv]; ;
        var usePosition = (Point3DBl)(Surface[uv] * world);

        var N = (Point3DBl)(Surface.Normals[uv] * world).Normalize;
        var T = (Point3DBl)(Surface.Tangents[uv] * world).Normalize;
        var B = T.Cross(N);
        MatrixBl<D3, D3> TBN = new MatrixBl<D3, D3>(T.X, T.Y, T.Z, 
                                                    B.X, B.Y, B.Z, 
                                                    N.X, N.Y, N.Z);

        var norm = (Point3DBl)(Normal[uv + 0.5]).Normalize;

        var newNorm = norm * TBN;

        vertex.Color = (ambLight.Ambient(0.25) + dirLight.Diffuse())[usePosition, newNorm](clr);//dirLight.Specular(eye, 1d, .8) + ambLight.Ambient(0.3) + 

      });

      var Host0 = new Bling.Shaders.DX.WPFHostBl(this, new PointBl(500, 500), Device) {
        LeftTop = 0d,
        ZIndex = 0,
      };
      Host = Host0.CurrentValue;
      sliderX.LeftTop = Host0.LeftBottom;
    }
  }
}
